package com.apes.fn.scm.retailOrder.service.orderFix;

import com.apes.crm.business.model.InsuranceCompanyDetail;
import com.apes.fn.business.fixedLoss.service.FixedLossToForeign;
import com.apes.fn.scm.insuranceRules.InsuranceRule;
import com.apes.fn.scm.insuranceRules.InsuranceRuleService;
import com.apes.fn.scm.retailOrder.model.RetailOrder;
import com.apes.fn.scm.retailOrder.repository.RetailOrderRepository;
import com.apes.fn.scm.retailOrder.service.account.RetailAccountData;
import com.apes.fn.scm.retailOrder.service.account.retail.InsuranceVoucherService;
import com.apes.fn.server.servicePlan.repository.ServicePlanItemRepository;
import com.apes.fn.server.servicePlan.service.ServicePlanceService;
import com.apes.framework.api.DomainService;
import com.apes.framework.api.SpringManager;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.plugin.esb.api.SimpleRequest;
import com.apes.framework.util.MapUtil;
import com.apes.framework.util.ReflectUtil;
import com.apes.scm.account.account.model.AccountingMethod;
import com.apes.scm.account.account.model.InventoryBatch;
import com.apes.scm.account.account.model.InventoryMode;
import com.apes.scm.account.account.service.InventoryService;
import com.apes.scm.account.tax.model.Tax;
import com.apes.scm.account.tax.service.TaxService;
import com.apes.scm.contract.model.Contract;
import com.apes.scm.contract.service.ContractService;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.voucher.model.Voucher;
import com.apes.scm.voucher.model.VoucherInventory;
import com.apes.scm.voucher.model.VoucherItem;
import com.apes.scm.voucher.repository.VoucherInventoryRepository;
import com.apes.scm.voucher.repository.VoucherRepository;
import com.apes.scm.voucher.service.BusinessType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 处理定损场景流错误数据
 *
 * @Author wuq
 * @Date 2021-8-20
 */
@Service
public class RetailFlowInsuranceDataUpdate extends DomainService {

    @Autowired
    private InventoryService inventoryService;
    @Autowired
    private VoucherRepository voucherRepository;
    @Autowired
    private VoucherInventoryRepository voucherInventoryRepository;
    @Autowired
    private RetailOrderRepository retailOrderRepository;
    @Autowired
    private InsuranceVoucherService insuranceVoucherService;
    @Autowired
    private TaxService taxService;


    /**
     * 场景：缺少基地对门店的采购，以及基地对保险公司销售
     * @param request {"id" :""}
     */
    public void basePurchaseAndInsuranceSale(SimpleRequest request){
        String id = request.get("id");
        RetailOrder retailOrder = retailOrderRepository.findOne(id);
        // 场景流不对就返回
        if (!"RO002".equals(retailOrder.getScene().getId())) return;
        List<Voucher> vouchers = voucherRepository.findAll(JpaDsl.toCriteriaByEq("origin", retailOrder.getId()));
        if (!vouchers.isEmpty()) return;        // 如果有生成完凭证就不再生成

        InsuranceRule insuranceRule = SpringManager.getBean(InsuranceRuleService.class)
                .findByDeptAndInsuranceCompany(retailOrder.getServiceDept(), retailOrder.getInsuranceCompany());
        if (Objects.isNull(insuranceRule)) throw new RuntimeException("没有找到对应的车型规则,，部门："+ retailOrder.getServiceDept().getId() + "，保险公司："+ retailOrder.getInsuranceCompany().getId());

        // 判断基地公司是否能直接对保险公司开票
        if (retailOrder.getServiceDept().getCompany().getId().equals(insuranceRule.getCompany().getId())) {
            /** 直接生成对保险公司的分销单 **/
            System.out.println("直接生成对保险公司的分销单");
        } else {
            /** 重新生成基地对门店的采购，以及对保险公司的销售 **/
            insuranceVoucherService.saleCompanyVoucher(retailOrder, insuranceRule.getCompany());
        }
    }


    /**
     * 场景：缺少基地对门店的采购，以及基地对保险公司销售
     * @param request {"id":""}
     */
    public void returnSale(SimpleRequest request){
        String id = request.get("id");
        RetailOrder retailOrder = retailOrderRepository.findOne(id);
        if (!"RO002".equals(retailOrder.getScene().getId())) return;     // 场景流不对就返回

        // 查找销售凭证
        List<Voucher> vouchers = voucherRepository.findAll(JpaDsl.toCriteriaByEq(
                "scene.id", "RO002", "origin", retailOrder.getId(), "voucherType", "CUSTOMER_SALE"));
        if (vouchers.isEmpty()) throw new RuntimeException("没有找到对应的销售凭证！");
        if (vouchers.size() > 1) throw new RuntimeException("找到多个销售凭证，请检查！");
        Voucher originSaleVoucher = vouchers.get(0);    // 原销售凭证

        // 销售退回
        returnSaleVoucher(retailOrder, originSaleVoucher);

        // 重新销售
        repeatSale(retailOrder, originSaleVoucher);
    }

    private void returnSaleVoucher(RetailOrder retailOrder, Voucher originSaleVoucher){
        // 销售退回凭证
        Voucher voucher = new Voucher();
        voucher.setReturned(true);
        voucher.setBusinessType(BusinessType.SALE_RETURN);

        voucher.setInventoryMode(InventoryMode.IM_OWN);     //设置库存模式：自有
        voucher.setAccountingMethod(AccountingMethod.AM_PURCHASE);  // 核算方式：经销

        ReflectUtil.copy(originSaleVoucher, voucher, "dept", "company", "clerk", "scene", "customerExpand");
        voucher.setPartner(originSaleVoucher.getPartner().getParty().getPartyRoleByType("Customer"));

        voucher.setOrigin(retailOrder.getId());
        voucher.setOriginBusinessType(retailOrder.getInnerBusinessType());
        voucher.setSource(originSaleVoucher.getId());       // 原销售凭证
        voucher.setSourceBusinessType(originSaleVoucher.getInnerBusinessType());

        // 明细数据
        voucher.setVoucherItems( retailOrder.getSaleItems().stream().map(
                retailOrderItem -> {

                    VoucherItem voucherItem = new VoucherItem();
                    ReflectUtil.copy(retailOrderItem, voucherItem, "product", "tax", "uom", "priceUnit");

                    voucherItem.setProductQty( -1 * Math.abs(retailOrderItem.getProductUomQty()) );
                    voucherItem.setOriginItemId(retailOrderItem.getId());
                    voucherItem.setSourceItemId(retailOrderItem.getId());

                    // 找原销售凭证中的明细行
                    originSaleVoucher.getVoucherItems().forEach( saleVoucherItem -> {
                        if (retailOrderItem.getProduct().getId().equals(saleVoucherItem.getProduct().getId())) {
                            voucherItem.setVoucherItem(saleVoucherItem);
                        }
                    });

                    return voucherItem;
                }).collect(Collectors.toSet()) );

        voucher = invoke("voucher.create", MapUtil.mapped(voucher));
        invoke("invoice.create", MapUtil.mapped(invoke("voucher.flow.invoice", MapUtil.mapped(voucher))));


        changeFrostQty(voucher, "调整定损数据，重新对保险公司销售");

    }

    protected void changeFrostQty(Voucher voucher, String remarks) {
        voucher.getVoucherItems().forEach(
                voucherItem -> {
                    VoucherInventory voucherInventory = voucherInventoryRepository.findByVoucherItem(voucherItem).stream().findAny().orElseThrow(() -> new RuntimeException("找不到批次信息！"));
                    InventoryBatch inventoryBatch = voucherInventory.getInventoryBatch();

                    // 冻结批次数量
                    inventoryService.changeFrostQty(inventoryBatch, inventoryBatch.getUom(), inventoryBatch.getPurchaseQty(),
                            voucher.getCompany(), voucher.getInnerBusinessType(), voucher.getId(),
                            String.valueOf(voucherItem.getId()), remarks);
                });
    }

    private void repeatSale(RetailOrder retailOrder, Voucher originSaleVoucher){
        Voucher voucher = new Voucher();
        voucher.setBusinessType(BusinessType.SALE_ORDER);

        ReflectUtil.copy(originSaleVoucher, voucher, "dept", "company", "clerk", "scene", "customerExpand");

        // 通过保险公司明细找保险公司客户
        InsuranceCompanyDetail companyDetail = SpringManager.getBean(FixedLossToForeign.class)
                .getInsuranceCompanyToClient(retailOrder.getInsuranceCompany(), retailOrder.getServiceDept());
        voucher.setPartner( companyDetail.getClient() );

        voucher.setInventoryMode(InventoryMode.IM_OWN);     //设置库存模式：自有
        voucher.setAccountingMethod(AccountingMethod.AM_PURCHASE);  // 核算方式：经销

        voucher.setSource(retailOrder.getId());
        voucher.setSourceBusinessType(retailOrder.getInnerBusinessType());
        voucher.setOrigin(retailOrder.getId());
        voucher.setOriginBusinessType(retailOrder.getInnerBusinessType());

        voucher.setVoucherItems(
                retailOrder.getSaleItems().stream().map(
                        retailOrderItem -> {
                            VoucherItem voucherItem = new VoucherItem();
                            ReflectUtil.copy(retailOrderItem, voucherItem, "product", "uom", "priceUnit");

                            Tax tax = taxService.getSaleTax(originSaleVoucher.getCompany(), retailOrderItem.getProduct());
                            voucherItem.setTax(tax);

                            voucherItem.setProductQty(retailOrderItem.getProductUomQty());
                            voucherItem.setOriginItemId(retailOrderItem.getId());
                            voucherItem.setSourceItemId(retailOrderItem.getId());
                            voucherItem.setDiscount(0d);
                            return voucherItem;
                        }).collect(Collectors.toSet())
        );
        double lossQuotationFeeAmt = voucher.getVoucherItems().stream().mapToDouble(VoucherItem::getLossQuotationFee).sum();
        voucher.setLossQuotationFeeAmt(lossQuotationFeeAmt);

        // 添加采购凭证批次以及供应商信息
        voucher.getVoucherItems().forEach(item -> {
            originSaleVoucher.getVoucherItems().forEach(purchaseVoucherItem -> {

                VoucherInventory voucherInventory = voucherInventoryRepository.findByVoucherItem(purchaseVoucherItem).stream()
                        .findAny().orElseThrow(() -> new RuntimeException("找不到批次信息！"));

                if (item.getProduct().getId().equals(voucherInventory.getProduct().getId())) {
                    item.setInventoryBatch(voucherInventory.getInventoryBatch());
                    item.setSupplier(purchaseVoucherItem.getSupplier());
                }
            });
        });

        // 创建账单
        voucher = invoke("voucher.create", MapUtil.mapped(voucher));

        //增加账单
        invoke("invoice.create", MapUtil.mapped(invoke("voucher.flow.invoice", MapUtil.mapped(voucher))));
    }


    public void reCreateInvoice(SimpleRequest request){
        String id = request.get("id");
        Voucher voucher = voucherRepository.findOne(id);
        invoke("invoice.create", MapUtil.mapped(invoke("voucher.flow.invoice", MapUtil.mapped(voucher))));
    }
}
